package com.bear.atlassianmcp.oauth.strategy;

import com.bear.atlassianmcp.common.util.SessionUtil;
import com.bear.atlassianmcp.oauth.config.OAuthProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 认证策略工厂
 * 根据配置和请求上下文选择合适的认证策略
 */
@Component
public class AuthenticationStrategyFactory {
    
    private static final Logger logger = LoggerFactory.getLogger(AuthenticationStrategyFactory.class);
    
    private final OAuthProperties oauthProperties;
    private final BasicAuthStrategy basicAuthStrategy;
    private final OAuthStrategy oauthStrategy;
    
    @Autowired
    public AuthenticationStrategyFactory(OAuthProperties oauthProperties,
                                       BasicAuthStrategy basicAuthStrategy,
                                       OAuthStrategy oauthStrategy) {
        this.oauthProperties = oauthProperties;
        this.basicAuthStrategy = basicAuthStrategy;
        this.oauthStrategy = oauthStrategy;
    }
    
    /**
     * 为 Jira 服务选择认证策略
     * 
     * @param toolContext 工具上下文
     * @return 适合的认证策略
     */
    public AuthenticationStrategy getJiraAuthStrategy(ToolContext toolContext) {
        return getAuthStrategy(AuthenticationStrategy.ServiceType.JIRA, toolContext);
    }
    
    /**
     * 为 Confluence 服务选择认证策略
     * 
     * @param toolContext 工具上下文
     * @return 适合的认证策略
     */
    public AuthenticationStrategy getConfluenceAuthStrategy(ToolContext toolContext) {
        return getAuthStrategy(AuthenticationStrategy.ServiceType.CONFLUENCE, toolContext);
    }
    
    /**
     * 根据服务类型和上下文选择认证策略
     * 基于请求头中的 Authorization 格式进行选择
     *
     * @param serviceType 服务类型
     * @param toolContext 工具上下文
     * @return 适合的认证策略
     */
    public AuthenticationStrategy getAuthStrategy(AuthenticationStrategy.ServiceType serviceType,
                                                ToolContext toolContext) {

        // 1. 优先检查请求头中的 Authorization 格式
        String authorization = getAuthorizationFromRequest(toolContext);

        if (authorization != null) {
            if (authorization.startsWith("OAuth ")) {
                // OAuth 令牌认证
                if (isOAuthEnabledAndConfigured(serviceType)) {
                    logger.debug("Using OAuth strategy for {} (OAuth token found in request)", serviceType);
                    return oauthStrategy;
                } else {
                    logger.warn("OAuth token found in request but OAuth not configured for {}, falling back to Basic Auth", serviceType);
                    return basicAuthStrategy;
                }
            } else if (authorization.startsWith("Basic ")) {
                // Basic Auth 认证
                logger.debug("Using Basic Auth strategy for {} (Basic auth found in request)", serviceType);
                return basicAuthStrategy;
            }
        }

        // 2. 如果请求头中没有明确的认证信息，检查 OAuth 配置
        if (isOAuthEnabledAndConfigured(serviceType)) {
            logger.info("OAuth enabled for {} but no authorization header found, OAuth authorization may be required", serviceType);
            return oauthStrategy;
        }

        // 3. 默认使用 Basic Auth
        logger.debug("Using Basic Auth strategy for {} (default fallback)", serviceType);
        return basicAuthStrategy;
    }
    
    /**
     * 检查 OAuth 是否启用并且配置完整
     */
    private boolean isOAuthEnabledAndConfigured(AuthenticationStrategy.ServiceType serviceType) {
        try {
            switch (serviceType) {
                case JIRA:
                    return oauthProperties.getJira().isEnabled() && 
                           isJiraOAuthConfigComplete();
                case CONFLUENCE:
                    return oauthProperties.getConfluence().isEnabled() && 
                           isConfluenceOAuthConfigComplete();
                default:
                    return false;
            }
        } catch (Exception e) {
            logger.warn("Error checking OAuth configuration for {}: {}", serviceType, e.getMessage());
            return false;
        }
    }
    
    /**
     * 检查 Jira OAuth 配置是否完整
     */
    private boolean isJiraOAuthConfigComplete() {
        OAuthProperties.JiraOAuth jiraConfig = oauthProperties.getJira();
        return jiraConfig.getBaseUrl() != null && !jiraConfig.getBaseUrl().trim().isEmpty() &&
               jiraConfig.getConsumerKey() != null && !jiraConfig.getConsumerKey().trim().isEmpty() &&
               jiraConfig.getPrivateKey() != null && !jiraConfig.getPrivateKey().trim().isEmpty();
    }
    
    /**
     * 检查 Confluence OAuth 配置是否完整
     */
    private boolean isConfluenceOAuthConfigComplete() {
        OAuthProperties.ConfluenceOAuth confluenceConfig = oauthProperties.getConfluence();
        return confluenceConfig.getBaseUrl() != null && !confluenceConfig.getBaseUrl().trim().isEmpty() &&
               confluenceConfig.getConsumerKey() != null && !confluenceConfig.getConsumerKey().trim().isEmpty() &&
               confluenceConfig.getPrivateKey() != null && !confluenceConfig.getPrivateKey().trim().isEmpty();
    }
    
    /**
     * 从请求中获取 Authorization 头信息
     */
    private String getAuthorizationFromRequest(ToolContext toolContext) {
        try {
            return SessionUtil.getAuthorization(toolContext);
        } catch (Exception e) {
            logger.debug("Error getting authorization from request: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 检查请求头中是否包含 Basic Auth（保留用于向后兼容）
     * @deprecated 使用 getAuthorizationFromRequest 替代
     */
    @Deprecated
    private boolean hasBasicAuthInRequest(ToolContext toolContext) {
        try {
            String authorization = SessionUtil.getAuthorization(toolContext);
            return basicAuthStrategy.isBasicAuth(authorization);
        } catch (Exception e) {
            logger.debug("Error checking Basic Auth in request: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 检查请求头中是否包含 OAuth Token
     */
    private boolean hasOAuthTokenInRequest(ToolContext toolContext) {
        try {
            String authorization = SessionUtil.getAuthorization(toolContext);
            return authorization != null && authorization.startsWith("OAuth ");
        } catch (Exception e) {
            logger.debug("Error checking OAuth token in request: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 获取认证策略的详细信息
     */
    public AuthStrategyInfo getAuthStrategyInfo(AuthenticationStrategy.ServiceType serviceType,
                                              ToolContext toolContext) {
        AuthenticationStrategy strategy = getAuthStrategy(serviceType, toolContext);
        String authorization = getAuthorizationFromRequest(toolContext);

        AuthStrategyInfo info = new AuthStrategyInfo();
        info.serviceType = serviceType;
        info.authenticationType = strategy.getAuthenticationType();
        info.strategyClass = strategy.getClass().getSimpleName();

        // 添加额外信息
        if (strategy instanceof OAuthStrategy) {
            info.hasValidToken = hasOAuthTokenInRequest(toolContext);
            info.oauthEnabled = isOAuthEnabledAndConfigured(serviceType);
            info.authorizationHeaderType = authorization != null && authorization.startsWith("OAuth ") ? "OAuth" : "None";
        } else if (strategy instanceof BasicAuthStrategy) {
            info.hasBasicAuthInRequest = hasBasicAuthInRequest(toolContext);
            info.authorizationHeaderType = authorization != null && authorization.startsWith("Basic ") ? "Basic" : "None";
        }

        return info;
    }
    
    /**
     * 强制使用 OAuth 策略（用于授权流程）
     */
    public AuthenticationStrategy forceOAuthStrategy(AuthenticationStrategy.ServiceType serviceType) {
        if (!oauthStrategy.supportsServiceType(serviceType)) {
            throw new RuntimeException("OAuth not supported or configured for " + serviceType);
        }
        
        logger.info("Forcing OAuth strategy for {}", serviceType);
        return oauthStrategy;
    }
    
    /**
     * 强制使用 Basic Auth 策略
     */
    public AuthenticationStrategy forceBasicAuthStrategy() {
        logger.debug("Forcing Basic Auth strategy");
        return basicAuthStrategy;
    }
    
    /**
     * 认证策略信息类
     */
    public static class AuthStrategyInfo {
        public AuthenticationStrategy.ServiceType serviceType;
        public AuthenticationStrategy.AuthenticationType authenticationType;
        public String strategyClass;
        public boolean hasValidToken;
        public boolean oauthEnabled;
        public boolean hasBasicAuthInRequest;
        public String authorizationHeaderType; // "Basic", "OAuth", "None"

        @Override
        public String toString() {
            return "AuthStrategyInfo{" +
                   "serviceType=" + serviceType +
                   ", authenticationType=" + authenticationType +
                   ", strategyClass='" + strategyClass + '\'' +
                   ", hasValidToken=" + hasValidToken +
                   ", oauthEnabled=" + oauthEnabled +
                   ", hasBasicAuthInRequest=" + hasBasicAuthInRequest +
                   ", authorizationHeaderType='" + authorizationHeaderType + '\'' +
                   '}';
        }
    }
    
    /**
     * 验证所有认证策略配置
     */
    public void validateAllConfigurations() {
        logger.info("Validating all authentication configurations...");
        
        try {
            // 验证 Basic Auth 策略
            basicAuthStrategy.validateAuthConfiguration();
            logger.info("Basic Auth configuration validated");
        } catch (Exception e) {
            logger.warn("Basic Auth configuration validation failed: {}", e.getMessage());
        }
        
        try {
            // 验证 OAuth 策略
            oauthStrategy.validateAuthConfiguration();
            logger.info("OAuth configuration validated");
        } catch (Exception e) {
            logger.warn("OAuth configuration validation failed: {}", e.getMessage());
        }
        
        logger.info("Authentication configuration validation completed");
    }
}
